--
-- DE2 (Cyclone-II) Entity for Interactive Project Game
-- Authors:
--      Abdulhamid Ghandour
--      Thomas John
--      Jaime Peretzman
--      Bharadwaj Vellore
--
-- Desc:
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity i2c_controller is
  
  port (
    clk        : in  std_logic;
    reset_n    : in  std_logic;
    read       : in  std_logic;
    write      : in  std_logic;
    chipselect : in  std_logic;
    address    : in  unsigned(3 downto 0);
    readdata   : out unsigned(31 downto 0);
    writedata  : in  unsigned(31 downto 0);
    sclk       : out std_logic;
    sdat       : inout std_logic;
    ack        : in std_logic
  );
end i2c_controller;

architecture rtl of i2c_controller is

  type ram_type is array(7 downto 0) of unsigned(31 downto 0);
  signal RAM : ram_type;
  signal ram_address : unsigned(2 downto 0);
  signal counter  : unsigned(31 downto 0);
  signal int_sclk : std_logic := '1';
  signal int_sdat : std_logic := '1';
  signal int_ack  : std_logic := '0';
begin
  ram_address <= address(2 downto 0);

  i2c_host_control: process (clk)
  begin
    if rising_edge(clk) then
      if reset_n = '0' then
        
      else
        if chipselect = '1' then
          if read = '1' then
            if to_integer(ram_address) = 2 then
              readdata(0) <= ack;
            else
              readdata <= RAM(to_integer(ram_address));
            end if;
          elsif write = '1' then
            RAM(to_integer(ram_address)) <= writedata;
          end if;
        end if;
      end if;
      RAM(7) <= counter;
    end if;
  end process i2c_host_control;

  timer: process (clk)
  begin
    if rising_edge(clk) then
      if reset_n = '0' then
        counter <= (others => '0');
      else
        counter <= counter + 1;
      end if;
    end if;
  end process timer;

  i2c_line_control: process (clk)
  begin
    if rising_edge(clk) then
      if reset_n = '0' then
      else
        int_sclk <= RAM(0)(0);
      end if;
    end if;
  end process i2c_line_control;

  sdat <= RAM(1)(0) when RAM(1)(1) = '1' else 'Z';
  sclk <= int_sclk;
end rtl;
